/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package sadseriesaldia;

import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.GregorianCalendar;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JTextArea;
import java.util.regex.*;
import nanoxml.*;

/**
 *
 * @author Rafael
 */
public class gestorLinks extends Thread {

    Thread hilo;
    private ArrayList<Serie> series;
    private Hashtable<String, String> linksNuevos;
    private ArrayList<String> servidores;
    private String estado = "pause";
    private static String configDir = System.getProperty("user.dir") + "//src//config.xml";
    private String salidaDir = "";
    private int periodicidad;
    JTextArea jTextArea1;

    /** Constructor del Hilo.
     */
    public gestorLinks(JTextArea jTextArea1) {
        this.jTextArea1 = jTextArea1;
        hilo = new Thread(this, "gestorLinks");
        hilo.start();
    }

    public synchronized void iniciar() {
        estado = "play";
    }

    public synchronized void pausar() {
        estado = "pause";
    }

    public synchronized void parar() {
        hilo.interrupt();
        estado = "parar";
    }

    /**
    cargarSeries: Funcion encargada de obtener los datos del xml pasado por consola
    @param archivo . Nombre del archivo xml
    @exception IOException en error de nombre de archivo
    @return void 
     **/
    private synchronized boolean cargarSeries(String archivo) throws java.io.IOException {
        this.series = new ArrayList<Serie>();
        this.servidores = new ArrayList<String>();
        Serie s;
        XMLElement xml = new XMLElement();
        FileReader reader = new FileReader(archivo);
        xml.parseFromReader(reader);

        String dato = null;
        String value = null;

        Enumeration enu = xml.enumerateChildren();

        while (enu.hasMoreElements()) {
            XMLElement child = (XMLElement) enu.nextElement();

            Enumeration enu2 = child.enumerateChildren();

            if (child.getName().equals("serie")) {
                s = new Serie();
                // Obtenemos los datos de la serie
                while (enu2.hasMoreElements()) {
                    XMLElement child2 = (XMLElement) enu2.nextElement();

                    dato = child2.getName();
                    value = child2.getContent();

                    //System.out.println(dato + ": " + value);
                    // Construimos la serie
                    if (dato.equals("nombre")) {
                        s.setNombre(value);
                    } else if (dato.equals("temporada")) {
                        s.setTemporada(Integer.parseInt(value));
                    } else if (dato.equals("capitulo")) {
                        s.setCapitulo(Integer.parseInt(value));
                    } else if (dato.equals("url")) {
                        s.setUrl(new URL(value));
                    } else {
                        System.out.println("Error lectura Capítulo");
                    }

                }
                // agregamos a la lista
                this.series.add(s);
            } else {
                while (enu2.hasMoreElements()) {
                    XMLElement child2 = (XMLElement) enu2.nextElement();

                    dato = child2.getName();
                    value = child2.getContent();

                    //System.out.println(dato + ": " + value);
                    // asignamos las propiedades
                    if (dato.equals("periodicidad")) {
                        periodicidad = Integer.parseInt(value);
                    } else if (dato.equals("servidor")) {
                        servidores.add(value);
                    } else if (dato.equals("DirSalida")) {
                        salidaDir = value;
                    } else {
                        System.out.println("Error lectura dato Configuracion");
                    }
                }
            }
        } //fin del while
        reader.close();
        return series.size() > 0;
    }//fin cargarSeries

    private synchronized void guardarArchivoConfig() {
        try {
            FileWriter fw = new FileWriter(configDir, false);
            fw.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
            fw.append("<root>\n"
                    + "    <config>\n");
            fw.append("        <periodicidad>" + periodicidad + "</periodicidad>\n");
            fw.append("        <DirSalida>" + salidaDir + "</DirSalida>\n");
            Iterator<String> itserv = servidores.iterator();
            while (itserv.hasNext()) {
                String serv = itserv.next();
                fw.append("        <servidor>" + serv + "</servidor>\n");
                fw.flush();
            }
            fw.append("    </config>\n");
            Iterator<Serie> it = series.iterator();
            while (it.hasNext()) {
                fw.append("    <serie>\n");
                Serie s = it.next();
                fw.append("        <nombre>" + s.getNombre() + "</nombre>\n");
                fw.append("        <temporada>" + s.getTemporada() + "</temporada>\n");
                fw.append("        <capitulo>" + s.getCapitulo() + "</capitulo>\n");
                fw.append("        <url>" + s.getUrl() + "</url>\n");
                fw.append("    </serie>\n");
                fw.flush();
            }
            fw.append("</root>");
            fw.close();
        } catch (IOException ex) {
            Logger.getLogger(gestorLinks.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private String obtenerHoraProxVerificacion() {
        GregorianCalendar gc = new GregorianCalendar();
        gc.add(gc.SECOND, periodicidad);
        String hora = "";
        hora += gc.get(gc.HOUR) + ":" + gc.get(gc.MINUTE) + ":" + gc.get(gc.SECOND);
        if (gc.get(gc.AM_PM) == 0) {
            hora += " AM.";
        } else {
            hora += " PM.";
        }
        return hora;
    }

    public synchronized boolean obtenerLink(URL url, String serie) {
        boolean encontrado = false;
        String linea = "";
        String txt = "";
        String link = "";
        String pat = "(?i)<a([^>]+)>(.+?)</a>";
        Pattern patron = Pattern.compile(pat);
        try {
            BufferedReader bs = new BufferedReader(new InputStreamReader(url.openStream()));
            while ((linea = bs.readLine()) != null) {
                txt += linea + "\n";
            }
            Matcher m = patron.matcher(txt);
            // para cada tag <a>
            while (m.find()) {
                linea = m.group(0);
                if (!linea.toLowerCase().contains("linkd")
                        && linea.toLowerCase().contains("descargar")) {
                    System.out.println(linea);
                    // para cada servidor
                    Iterator<String> it = servidores.iterator();
                    while (it.hasNext()) {
                        String serv = it.next();
                        System.out.println("Servidor: " + serv);
                        if (linea.toLowerCase().contains(serv)) {
                            //System.out.println("Link: " + linea);
                            // Obtenemos el url para descargar...
                            Pattern enlace = Pattern.compile("\\s*(?i)href\\s*=\\s*(\"([^\"]*\")|'[^']*'|([^'\">\\s]+))");
                            Matcher m2 = enlace.matcher(linea);

                            while (m2.find()) {
                                link = m2.group(0);
                                link = link.substring(7, link.length() - 1);
                                System.out.println(link);

                                linksNuevos.put(serie + " - " + serv, link);
                            }
                            // paramos cuando obtenemos el link del primer servidor
                            break;
                        }
                    }
                }
            }


        } catch (Exception ex) {
            System.out.println(ex);
        }
        return encontrado;
    }

    public synchronized boolean obtenerLink(URL url, String serie, String temporada, String capitulo) {
        String txt = "";
        String linea = "";
        String link = "";
        boolean encontrado = false;

        String pat = "(?i)<a([^>]+)>(.+?)</a>";
        //System.out.println("A buscar: " + pat);
        Pattern patron = Pattern.compile(pat);

        try {
            BufferedReader bs = new BufferedReader(new InputStreamReader(url.openStream()));
            while ((linea = bs.readLine()) != null) {
                txt += linea + "\n";
            }
            Matcher m = patron.matcher(txt);
            //System.out.println("Macheo:\n");
            while (m.find()) {
                linea = m.group(0);
                if (linea.contains(temporada + "x" + capitulo)) {
                    //System.out.println("Link: " + linea);
                    // Obtenemos el url para descargar...
                    Pattern enlace = Pattern.compile("\\s*(?i)href\\s*=\\s*(\"([^\"]*\")|'[^']*'|([^'\">\\s]+))");
                    Matcher m2 = enlace.matcher(linea);
                    // Se ejecuta una sola vez...
                    while (m2.find()) {
                        link = m2.group(0);
                        link = link.substring(7, link.length() - 1);
                    }
                    // procedemos a buscar el link del servidor
                    obtenerLink(new URL(link), serie);
                    encontrado = true;
                    break;
                }
            }
            //System.out.println(link);
        } catch (Exception ex) {
            System.out.println(ex);
        }
        return encontrado;
    }

    public void run() {
        boolean cambios = false;
        boolean cSeries;
        // el hilo va a estar corriendo siempre
        try {
            // Cargo las series por primera vez del archivo de ocnfiguracion
            cSeries = cargarSeries(configDir);
            linksNuevos = new Hashtable<String, String>();
            // Mientras no pare
            while (!estado.equals("parar")) {
                if (estado.equals("play")) {
                    if (cSeries) {
                        jTextArea1.append("Series a buscar cargadas con éxito!\n");
                        // iteramos sobre las series
                        Iterator<Serie> it = series.iterator();
                        while (it.hasNext()) {
                            Serie s = it.next();
                            jTextArea1.append("Buscando enlaces para: " + s.getNombre() + "\n");
                            // Obtenemos la pag web para esa serie
                            DecimalFormat format = new DecimalFormat("00");
                            //String temp = "" + format.format(s.getTemporada());
                            String cap = "" + format.format(s.getCapitulo());

                            //Si para la serie encontramos un link nuevo.
                            if (obtenerLink(s.getUrl(), s.getNombre(), "" + s.getTemporada(), cap)) {
                                jTextArea1.append("Nuevo capítulo: " + s.getNombre()
                                        + " " + s.getTemporada() + "x" + cap + "\n");
                                //Aumentamos el proximo capitulo
                                s.aumentarCapitulo();
                                cambios = true;
                            }
                        }

                        try {
                            // si hay cambios en el capitulo se modifica el config
                            if (cambios) {
                                guardarArchivoConfig();
                                System.out.println("Cambios guardados");
                                cambios = false;
                            }
                            guardar_pasarJdownloader();
                            jTextArea1.append("La próxima búsqueda se hará a las "
                                    + obtenerHoraProxVerificacion() + "\n");
                            hilo.sleep((periodicidad * 1000));
                        } catch (InterruptedException ie) {
                        }
                    } else {
                        jTextArea1.setText("No existen series para verificar capitulos nuevos.\n");
                    }
                }
                // Si no entro en el if es porque esta en pause
            }
        } catch (Exception ex) {
            Logger.getLogger(gestorLinks.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private void guardar_pasarJdownloader() {
        try {
            FileWriter salida = new FileWriter(salidaDir + "//Enlaces.txt", false);
            Set<String> set = linksNuevos.keySet();
            Iterator<String> it = set.iterator();
            String llave = "", item = "", itemJd = "";

            while (it.hasNext()) {
                llave = it.next();
                itemJd += linksNuevos.get(llave) + "\n";
                item += llave + ": " + linksNuevos.get(llave) + "\n";
            }
            salida.append(item);
            salida.close();
            // Copiamos al clipboard
            Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
            StringSelection ss = new StringSelection(itemJd);
            cb.setContents(ss, ss);

        } catch (IOException ex) {
            Logger.getLogger(gestorLinks.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}
